package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"time"
)

//缓冲区大小
const (
	N      = 5   //传送带缓冲区容量
	m      = 3   // 厨师数目
	n      = 10  //顾客数目
	capAll = 100 //预计要做寿司数
)

//传送带
var Ch = make(chan int, N)
var countShousi = 0
var (
	logFileName = flag.String("log", "cServer.log", "Log file name")
)

type Cook struct {
	name    string
	capAll  int           //已定工作量
	capNow  int           //已做寿司量
	oneTime time.Duration //做一个寿司需要的时间
}

type Customer struct {
	name     string
	shiLiang int           //食量
	shiSu    time.Duration //吃一个寿司的时间

}

func (co *Cook) Produce(in chan<- int) {
	for ; countShousi < capAll; countShousi++ {
		time.Sleep(co.oneTime)
		in <- countShousi
		co.capNow++
		fmt.Println(co.name+"生产了寿司", countShousi)
		log.Println(co.name+"生产了寿司", countShousi)

	}
}
func (cu *Customer) Consume(out <-chan int) {
	for i := 0; i < cu.shiLiang; i++ {
		j := <-out
		time.Sleep(cu.shiSu)
		fmt.Println(cu.name+"吃了寿司", j)
		log.Println(cu.name+"吃了寿司", j)
	}
}
func printRes() {
	log.Println("---------------------------------------------------------------------")
	log.Printf("工作完成，闭店\n")
	log.Printf("已做寿司：%v，传送带现有寿司数：%v\n", countShousi, len(Ch))
	log.Println("---------------------------------------------------------------------")
	log.Println("---------------------------------------------------------------------")

}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	//set logfile Stdout
	logFile, logErr := os.OpenFile(*logFileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	if logErr != nil {
		fmt.Println("Fail to find", *logFile, "cServer start Failed")
		os.Exit(1)
	}
	log.SetOutput(logFile)
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("---------------------------------------------------------------------")
	log.Println("---------------------------------------------------------------------")
	log.Println("程序正常启动")
	defer printRes()
	cookes := [m]Cook{
		{"厨师A", 50, 0, 2e9},
		{"厨师B", 30, 0, 3e9},
		{"厨师C", 35, 0, 4e9},
	}
	customers := [n]Customer{
		{"顾客A", 5, 3e9},
		{"顾客B", 3, 4e9},
		{"顾客C", 6, 3e9},
		{"顾客D", 2, 2e9},
		{"顾客F", 1, 6e9},
		{"顾客G", 7, 2e9},
		{"顾客H", 4, 2e9},
		{"顾客I", 1, 4e9},
		{"顾客J", 6, 3e9},
		{"顾客K", 4, 5e9},
	}
	var cookInformation string
	var cusInformation string
	for i := 0; i < m; i++ {
		cookInformation += "\t" + cookes[i].name + "\t" +
			fmt.Sprintf("%v\t", cookes[i].capNow) +
			fmt.Sprintf("%v\t\n", cookes[i].oneTime)
	}
	log.Printf("\n厨师数目：%v 位； \n昨日定下总制作寿司量：%v；\n传送带容量：%v ;\n"+
		"具体厨师信息如下：\n"+
		"\t姓名\t已定寿司量\t已做寿司量\t做一个寿司的时间\t\n%v", m, capAll, N, cookInformation)
	for i := 0; i < n; i++ {
		cusInformation += "\t" + customers[i].name + "\t" +
			fmt.Sprintf("%v\t", customers[i].shiLiang) +
			fmt.Sprintf("%v\t\n", customers[i].shiSu)
	}
	log.Printf("\n顾客数目：%v 位；具体顾客信息如下：\n"+
		"\t姓名\t食量\t吃一个寿司的时间\t\n%v", n, cusInformation)
	for i := 0; i < m; i++ {
		go cookes[i].Produce(Ch)
	}
	for i := 0; i < n; i++ {
		go customers[i].Consume(Ch)
	}

	time.Sleep(1e11)
}
